package com.dhgate.spu.analysis.consts;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.dhgate.spu.analysis.bean.Attr;
import com.dhgate.spu.analysis.bean.ExtractKeyword;
import com.dhgate.spu.analysis.bean.ProdLine;
import com.dhgate.spu.analysis.bean.SpuStandard;
import com.dhgate.spu.analysis.collector.ICollector;
import com.dhgate.spu.analysis.dao.DAOFactory;
import com.dhgate.spu.analysis.util.ComparatorUtil;
import com.dhgate.spu.analysis.util.StringUtil;
import com.dhgate.spu.analysis.util.CommonUtil;

/**
 * @author: wangguodong
 * @create: 2014-3-6 下午5:25:36
 * @description: 每个产品线上对应的spu标准常量
 */
public class SpuStandardConsts {
	public static final Logger logger = LoggerFactory.getLogger(SpuStandardConsts.class);
	private static Map<String, ProdLine> PROD_LINE_ID_2_PROD_LINE_MAP = new HashMap<String, ProdLine>();

	private static final String COLLECTOR_PACKAGE_NAME = "com.dhgate.spu.analysis.collector.";

	public static ProdLine getProdLine(String prodLineId) {
		ProdLine prodLine = PROD_LINE_ID_2_PROD_LINE_MAP.get(prodLineId);
		return prodLine;
	}

	public static String getAttrValIds(String prodLineId) {
		ProdLine prodLine = PROD_LINE_ID_2_PROD_LINE_MAP.get(prodLineId);
		if (prodLine == null) {
			return null;
		}
		return prodLine.getAttrValIds();
	}

	public static List<SpuStandard> getSpuStandList(String prodLineId) {
		ProdLine prodLine = PROD_LINE_ID_2_PROD_LINE_MAP.get(prodLineId);
		if (prodLine == null) {
			return null;
		}
		return prodLine.getSpuStandList();
	}

	public static String getAttrEnName(String prodLineId, String attrId) {
		ProdLine prodLine = PROD_LINE_ID_2_PROD_LINE_MAP.get(prodLineId);
		if (prodLine == null) {
			return null;
		}
		return prodLine.getAttrId2AttrEnNameMap().get(attrId);
	}

	public static String getAttrValEnName(String prodLineId, String attrValId) {
		ProdLine prodLine = PROD_LINE_ID_2_PROD_LINE_MAP.get(prodLineId);
		if (prodLine == null) {
			return null;
		}
		return prodLine.getAttrValId2AttrValEnNameMap().get(attrValId);
	}

	public static ICollector getCollector(String prodLineId) {
		ProdLine prodLine = PROD_LINE_ID_2_PROD_LINE_MAP.get(prodLineId);
		if (prodLine == null) {
			return null;
		}
		return prodLine.getCollector();
	}

	public static void init() throws Exception {
		initConfig();
		initAttr();
	}

	public static void initAttr() throws Exception {
		Iterator<ProdLine> prodLineIt = PROD_LINE_ID_2_PROD_LINE_MAP.values().iterator();
		while (prodLineIt.hasNext()) {
			initProdLine(prodLineIt.next());
		}
	}

	public static void initConfig() throws Exception {

		List<ProdLine> prodLineList = new ArrayList<ProdLine>();
		Map<String, ProdLine> prodLineId2ProdLineMap = new HashMap<String, ProdLine>();

		try {
			logger.info("InitSpuStandard begin");
			Set<String> collectorNameSet = new HashSet<String>();
			Map<String, ICollector> collectorName2InstanceMap = new HashMap<String, ICollector>();
			// 获得XML文档对象
			SAXReader reader = new SAXReader();
			Document document = reader.read(new File(SysConsts.CONST_SPU_STANDARD_XML_PATH));
			List<Element> prodLineEles = document.getRootElement().elements("prodLine");
			for (Element element : prodLineEles) {
				ProdLine prodLine = new ProdLine();
				String prodLineId = element.attributeValue("id");
				String resourcesfiles = element.attributeValue("resourcesfiles");
				prodLine.setProdLineId(prodLineId);
				prodLine.setResourcesfiles(resourcesfiles);
				prodLineList.add(prodLine);
				prodLineId2ProdLineMap.put(prodLineId, prodLine);
				prodLine.setSpuStandList(getSpuStandardList(element));
				String collectorName = element.attributeValue("collector");
				if (StringUtil.isEmpty(collectorName)) {
					collectorName = "StandardCollector";
				}
				prodLine.setCollectorName(collectorName);
				collectorNameSet.add(collectorName);
			}

			InitcollectorName2InstanceMap(collectorNameSet, collectorName2InstanceMap);
			for (ProdLine prodLine : prodLineList) {
				prodLine.setCollector(collectorName2InstanceMap.get(prodLine.getCollectorName()));
			}

			PROD_LINE_ID_2_PROD_LINE_MAP = prodLineId2ProdLineMap;
			logger.info("InitSpuStandard end PROD_LINE_ID_2_PROD_LINE_MAP.size" + PROD_LINE_ID_2_PROD_LINE_MAP.size());
		} catch (Exception e) {
			logger.info("error:" + e);
			e.printStackTrace();
			throw new Exception("error:" + e);
		}
	}

	private static void InitcollectorName2InstanceMap(Set<String> collectorNameSet, Map<String, ICollector> collectorName2InstanceMap)
			throws ClassNotFoundException, InstantiationException, IllegalAccessException, Exception {
		collectorNameSet.add("StandardCollector");
		Iterator<String> it = collectorNameSet.iterator();

		while (it.hasNext()) {
			String collectorName = it.next();
			if (StringUtil.isEmpty(collectorName)) {
				continue;
			}
			Class c = Class.forName(COLLECTOR_PACKAGE_NAME + collectorName);
			ICollector collector = (ICollector) c.newInstance();
			collector.init();
			collectorName2InstanceMap.put(collectorName, collector);
		}
	}

	public static void initProdLine(ProdLine prodLine) throws Exception  {
		logger.info("initProdLine begin prodLineId:" + prodLine.getProdLineId());
		Map<String, String> attrId2attrEnNameMap = new HashMap<String, String>();
		Map<String, List<String>> enName2ValIdsMap = new HashMap<String, List<String>>();
		Map<String, String> attrValId2AttrIdMap = new HashMap<String, String>();

		List<SpuStandard> spuStandList = prodLine.getSpuStandList();
		if (spuStandList == null || spuStandList.size() == 0) {
			return;
		}
		StringBuffer attrIdsSB = getAttrIdsSB(spuStandList);

		List<Attr> attrList = DAOFactory.getDAOInstance().getAttrList(prodLine.getProdLineId(),
				attrIdsSB.substring(0, attrIdsSB.length() - 1));
		StringBuffer attrValIdsSB = new StringBuffer();
		for (Attr attr : attrList) {
			String attrId = attr.getAttrId() + "";
			for (long attrValId : attr.getAttrValIds()) {
				attrValId2AttrIdMap.put("" + attrValId, attrId);
				attrValIdsSB.append(attrValId + ",");
			}
			attrId2attrEnNameMap.put(attr.getAttrId() + "", attr.getAttrName());
		}

		prodLine.setAttrId2AttrEnNameMap(attrId2attrEnNameMap);
		prodLine.setAttrValIds(attrValIdsSB.substring(0, attrValIdsSB.length() - 1).toString());
		prodLine.setAttrIds(attrIdsSB.substring(0, attrIdsSB.length() - 1).toString());
		prodLine.setAttrValId2AttrValEnNameMap(DAOFactory.getDAOInstance().getAttrValMap(prodLine.getAttrIds()));

		Iterator<Entry<String, String>> attrIt = prodLine.getAttrValId2AttrValEnNameMap().entrySet().iterator();
		while (attrIt.hasNext()) {
			Entry<String, String> entry = attrIt.next();
			List<String> attrValIds = enName2ValIdsMap.get(entry.getValue());
			if (attrValIds == null) {
				attrValIds = new ArrayList<String>();
				enName2ValIdsMap.put(entry.getValue(), attrValIds);
			}
			attrValIds.add(entry.getKey());
		}
		prodLine.setAttrValEnName2AttrValIdListMap(enName2ValIdsMap);
		prodLine.setAttrValId2AttrIdMap(attrValId2AttrIdMap);
		//初始化data_map
		String resourcesfiles = prodLine.getResourcesfiles();
		if (StringUtils.isNotBlank(resourcesfiles)) {
			logger.debug("resourcesfiles=" + resourcesfiles);
			//"spubrand1-spumodel2-843500.txt,spuchipmodel-2.txt"
			String[] filenameArr = resourcesfiles.split(",");
			for (String filename : filenameArr) {
				//初始化文件
				initProdLineDataMap(prodLine, filename);
			}
		}
		logger.info("prodLine.getData_map()="+prodLine.getData_map());
		logger.info("initProdLine end prodLineId:" + prodLine.getProdLineId());
	}
	private static void initProdLineDataMap(ProdLine prodLine, String filename) throws Exception {
		logger.info("initProdLineDataMap start prodLineId:" + prodLine.getProdLineId());
		List<String> confFieldList = getConfFieldList(filename);
		Map<String, Map<String, List<String>>> map = null;
		Map<String, String> enName2attrValIdMap = null;
		List<String> list = null;
		List<String> enNameList = new ArrayList<String>();
		InputStreamReader fr;
		try {
			String filePath = SysConsts.BASE_DIR + filename;
			fr = new InputStreamReader(new FileInputStream(filePath));

			BufferedReader br = new BufferedReader(fr);
			String line = br.readLine();
			
			while (line != null) {
				line = line.toLowerCase();
				if (StringUtil.isEmpty(line)) {
					line = br.readLine();
					continue;
				}
				//1188281:Meizu:魅族|M8,M9,MX,MX2,MX3
				String[] attrDatas = line.split("\\|");
				//&& line.indexOf(":")!=-1
				//关联的，2个字段的文件名
				if (filename.contains("-")) { //1188281:Meizu:魅族|M8,M9,MX,MX2,MX3
					if (map == null) {
						map = new HashMap<String, Map<String, List<String>>>();
					}
					Map<String, List<String>> map2 = new HashMap<String, List<String>>();
					String attrValId = "";
					for (int i = 0; i < attrDatas.length; i++) {
						List<String> dataList = new ArrayList<String>();
						if (attrDatas[i].indexOf(":") != -1) {
							String[] array = attrDatas[0].split(":");
							attrValId = array[0].trim();
							String enName = array[1].trim();
							dataList.add(enName);
							enNameList.add(enName);
							if (enName2attrValIdMap == null) {
								enName2attrValIdMap = new HashMap<String, String>();
							}
							enName2attrValIdMap.put(enName,attrValId);
						} else {
							String[] valArr = attrDatas[i].split(",");
							dataList = Arrays.asList(valArr);
						}
						map2.put(confFieldList.get(i), dataList);
					}
					map.put(attrValId, map2);

				}else {//一个字段的文件名
					if (line.contains(":")) { //1188281:Meizu:魅族
						String[] array = line.split(":");
						String attrValId = array[0].trim();
						String enName = array[1].trim();
						enNameList.add(enName);
						if (enName2attrValIdMap == null) {
							enName2attrValIdMap = new HashMap<String, String>();
						}
						enName2attrValIdMap.put(enName,attrValId);

					} else {// a,b
						if (list == null) {
							list = new ArrayList<String>();
						}
						String[] valArr = line.split(",");
						for(String val:valArr){
							list.add(val.trim());
						}
					}
				}

				line = br.readLine();
			}
			br.close();
		} catch (Exception e) {
			logger.error("readFile " + SysConsts.BASE_DIR + filename + " error:" + e);
			e.printStackTrace();
			throw new Exception("readFile " + SysConsts.BASE_DIR + filename + " error:" + e);
		}

		if (list != null) {// a,b
			Collections.sort(list, ComparatorUtil.STR_LENGTH_COMPARATOR);
			prodLine.getData_map().put(filename + "2", list);
			
		} else if (map != null) {//1188281:Meizu:魅族|M8,M9,MX,MX2,MX3
			prodLine.getData_map().put(filename + "1", map);
			prodLine.getFilename2enNamelistMap().put(filename + "1", enNameList);
			prodLine.getFilename2ennametoattrvalidMap().put(filename + "1", enName2attrValIdMap);
		} else {//1188281:Meizu:魅族
			prodLine.getData_map().put(filename + "3", enName2attrValIdMap);
			prodLine.getFilename2enNamelistMap().put(filename + "3", enNameList);
		}
		logger.info("initProdLineDataMap end prodLineId:" + prodLine.getProdLineId());
	}

	//根据文件名，得到配置的字段,如:brand
	private static List<String> getConfFieldList(String filename) {
		if (StringUtils.isBlank(filename)) {
			return null;
		}
		//去掉.txt
		filename = filename.substring(0, filename.length() - 4);
		List<String> confFieldList = new ArrayList<String>();
		String[] filenameParts = filename.split("-");
		for (String part : filenameParts) {
			//			spubrand#843500-spumodel.txt
			if (part.startsWith("spu")) {
				if (part.contains("#")) {
					part = part.substring(0, part.indexOf("#"));
				}
				confFieldList.add(part);
			}
		}
		return confFieldList;
	}
	private static StringBuffer getAttrIdsSB(List<SpuStandard> spuStandList) {
		Set<Long> attrIdSet = new HashSet<Long>();
		StringBuffer attrIdsSB = new StringBuffer();
		for (SpuStandard spuStand : spuStandList) {
			if (spuStand.getAttrIdSelect() == null || spuStand.getAttrIdSelect().size() == 0) {
				continue;
			}
			for (Long attrId : spuStand.getAttrIdSelect()) {
				if (!attrIdSet.contains(attrId)) {
					attrIdsSB.append(attrId + ",");
				}
				attrIdSet.add(attrId);
			}
		}
		return attrIdsSB;
	}

	private static List<SpuStandard> getSpuStandardList(Element element) throws Exception {
		List<SpuStandard> spuStandList = new ArrayList<SpuStandard>();
		List<Element> spuEles = element.elements();
		for (Element spuStandEle : spuEles) {
			SpuStandard spuStand = new SpuStandard();
			spuStand.setId(spuStandEle.attributeValue("id"));
			spuStand.setAttrIdList(getAttrIdList(spuStandEle, "attrIds"));
			spuStand.setAttrIdSelect(getAttrIdList(spuStandEle, "attrIds"));
			spuStand.setAbandonMap(getMap(spuStandEle, "abandonAttrValIds"));
			spuStand.setKeyMap(getMap(spuStandEle, "keyAttrValIds"));
			spuStand.setValidMap(getMap(spuStandEle, "validValues"));
			spuStand.setExtFieldList(getExtFieldList(spuStandEle));
			spuStand.setExtractKeyword(getExtractKeyword(spuStandEle, "extractKeyword"));
			// 开始组装attrIDSelect
			List<Long> attrIdSelect = spuStand.getAttrIdSelect();
			if (spuStand.getAbandonMap() != null) {
				Set<Long> abandons = spuStand.getAbandonMap().keySet();

				for (Long id : abandons) {
					if (!attrIdSelect.contains(id)) {
						attrIdSelect.add(id);
					}
				}
			}
			if (spuStand.getKeyMap() != null) {
				Set<Long> keys = spuStand.getKeyMap().keySet();
				for (Long id : keys) {
					if (!attrIdSelect.contains(id)) {
						attrIdSelect.add(id);
					}
				}
			}
			if (attrIdSelect != null) {
				Collections.sort(attrIdSelect);
			}
			spuStandList.add(spuStand);
		}
		return spuStandList;
	}

	private static ExtractKeyword getExtractKeyword(Element spuStandEle, String eleName) throws Exception {
		ExtractKeyword exkey = null;
		Element extractKeywordEle = spuStandEle.element(eleName);
		if (extractKeywordEle == null) {
			return null;
		}
		String names = extractKeywordEle.elementText("sourceFiledNames");
		String fileName = extractKeywordEle.elementText("keywords");
		if (StringUtil.isNotEmpty(names) && StringUtils.isNotEmpty(fileName)) {
			exkey = new ExtractKeyword();
			exkey.setSourceFieldNames(names.split(","));
			try {
				String content = getText(SysConsts.BASE_DIR + fileName);
				String[] keyArray = content.split(";");
				List<Set<String>> list = new ArrayList<Set<String>>();
				for (String keys : keyArray) {
					list.add(CommonUtil.getKeywordSet(keys));
				}
				exkey.setKeywordSet(list);
			} catch (Exception e) {
				throw e;
			}
		}
		return exkey;
	}

	public static String getText(String FileName) throws Exception {
		File file = new File(FileName);
		StringBuffer sb = new StringBuffer();
		BufferedReader reader = new BufferedReader(new FileReader(file));
		String s = "";
		while ((s = reader.readLine()) != null) {
			sb.append(s);
		}

		return sb.toString();
	}

	private static Map<Long, Set<Long>> getMap(Element ele, String eleName) {
		Element attrIdsEle = ele.element(eleName);
		if (attrIdsEle == null) {
			return null;
		}

		String text = attrIdsEle.getText();
		if (StringUtil.isEmpty(text)) {
			return null;
		}
		String[] vals = text.split(";");
		Map<Long, Set<Long>> map = new HashMap<Long, Set<Long>>();
		for (String val : vals) {
			String[] attr = val.split(":");
			String[] attrvals = attr[1].split(",");
			Set<Long> valSet = new HashSet<Long>();
			for (String attrVal : attrvals) {
				valSet.add(Long.parseLong(attrVal));
			}
			map.put(Long.parseLong(attr[0]), valSet);
		}
		return map;
	}

	private static List<Long> getAttrIdList(Element spuStandEle, String eleName) {
		Element attrIdsEle = spuStandEle.element(eleName);
		if (attrIdsEle == null) {
			return null;
		}

		String attrIds = attrIdsEle.getText();
		if (StringUtil.isEmpty(attrIds)) {
			return null;
		}

		List<Long> attrIdList = new ArrayList<Long>();
		for (String attrId : attrIds.split(",")) {
			attrIdList.add(Long.parseLong(attrId));
		}

		Collections.sort(attrIdList);
		return attrIdList;
	}

	private static List<String> getExtFieldList(Element spuStandEle) {
		Element attrIdsEle = spuStandEle.element("extFields");
		if (attrIdsEle == null) {
			return null;
		}

		String attrIds = attrIdsEle.getText();
		if (StringUtil.isEmpty(attrIds)) {
			return null;
		}

		List<String> extFieldList = new ArrayList<String>();
		for (String extField : attrIds.split(",")) {
			extFieldList.add(extField);
		}

		return extFieldList;
	}

	public static void main(String[] args) throws Exception {
		SpuStandardConsts.initConfig();
		ProdLine pdl = SpuStandardConsts.PROD_LINE_ID_2_PROD_LINE_MAP.get("19960");
		System.out.println(pdl.getSpuStandList().get(1).getAttrIdList());
		System.out.println(pdl.getSpuStandList().get(3).getExtractKeyword().getSourceFieldNames().length);
	}
}
